package service

import (
	"fmt"
	"log"
	"net/http"
	"strconv"
	"strings"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/lzppppppp/virapaksa-go/internal/monitor_config/handler"
	"github.com/lzppppppp/virapaksa-go/internal/monitor_config/model"
	"github.com/lzppppppp/virapaksa-go/internal/monitor_config/repository"
	gmidwa "github.com/lzppppppp/virapaksa-go/pkg/middleware"
	"github.com/spf13/viper"
)

type transData struct {
	Data []model.ApplyTrackNumber
	Dc   []string
}

// var monitorDatacenter string

// 前端调用接口，展示数据
func GetMonitorApplyData(context *gin.Context) {

	monitorDatacenter := context.Param("datacenter") // 获取前端发送的GET请求参数
	monitorType := context.Param("type")             // 获取前端发送的GET请求参数

	if monitorType == "" {
		context.JSON(http.StatusBadRequest, "Param is null")
	}

	DB := repository.GetDB()
	var Data []model.ApplyTrackNumber

	DB.Table(monitorType + "_track_numbers_" + monitorDatacenter).Find(&Data)

	context.JSON(http.StatusOK, Data)
}

// 接收前端部署信号，Launch AWX
func PostMonitorApplyData(context *gin.Context) {

	DB := repository.GetDB()
	var param transData
	err := context.BindJSON(&param) // 接收前端参数

	if err != nil {
		context.JSON(500, gin.H{"err": err})
		log.Printf("ERROR: Launch jobs failed")
		return
	}

	funcVar := gmidwa.FuncVar{ // 获取配置文件中的awx信息
		IP:    viper.GetString("awx.server.ip"),
		Port:  viper.GetString("awx.server.port"),
		Token: viper.GetString("awx.server.token"),
	}
	awxConfigInfo := gmidwa.AwxConfigInfo{ // 初始化awx结构体变量
		InstanceGrouId: viper.GetInt("awx.id.instance_group." + param.Dc[0]),
		EnvID:          viper.GetString("awx.env.sc"),
		CredentialId:   viper.GetInt("awx.id.credential." + param.Dc[0]),
	}

	for _, value := range param.Data { // 根据流水号获取数据推送

		trackNumberParts := strings.Split(value.TrackNumber, "-")
		var tableNumber struct { //
			TrackNumberTable string
		}
		var keywordsApply []model.KeywordsApply
		var keywordsApplyReplace []model.MonitorReplaceApply
		var keywordsApplyDelete []model.MonitorDeleteApply

		var awxHostVarArr []gmidwa.AwxHostVar

		// 根据track_number从track_numbers表中获取table_number_track
		DB.Table(strings.ToLower(trackNumberParts[1])+"_track_numbers_"+param.Dc[0]).Where("track_number = ?", value.TrackNumber).Select("track_number_table").Find(&tableNumber)

		var jobTemplate string
		switch strings.ToLower(trackNumberParts[2]) {
		case "new":
			DB.Table(strings.ToLower(trackNumberParts[1])+"_applies_"+param.Dc[0]).Where("track_number = ?", tableNumber.TrackNumberTable).Find(&keywordsApply)
			for _, value := range keywordsApply {
				awxHostVar := gmidwa.AwxHostVar{
					IP:  value.IP,
					Var: value.Keyword,
				}
				awxHostVarArr = append(awxHostVarArr, awxHostVar)
			}
			jobTemplate = viper.GetString("awx.name.job_template.exporter")
		case "replace":
			DB.Table(strings.ToLower(trackNumberParts[1])+"_replace_"+param.Dc[0]).Where("track_number = ?", tableNumber.TrackNumberTable).Find(&keywordsApplyReplace)
			for _, value := range keywordsApplyReplace {
				awxHostVar := gmidwa.AwxHostVar{
					IP:  value.IP,
					Var: value.Sourcekeywords + "," + value.Destkeywords,
				}
				awxHostVarArr = append(awxHostVarArr, awxHostVar)
			}
			jobTemplate = viper.GetString("awx.name.job_template.monitor-modify")
		case "delete":
			DB.Table(strings.ToLower(trackNumberParts[1])+"_delete_"+param.Dc[0]).Where("track_number = ?", tableNumber.TrackNumberTable).Find(&keywordsApplyDelete)
			for _, value := range keywordsApplyDelete {
				awxHostVar := gmidwa.AwxHostVar{
					IP: value.IP,
				}
				if value.Keyword != "" {
					awxHostVar.Var = value.Keyword
				}
				awxHostVarArr = append(awxHostVarArr, awxHostVar)
			}
			jobTemplate = viper.GetString("awx.name.job_template.monitor-modify")
		default:
		}

		funcAwxLaunch := gmidwa.FuncAwxLaunch{
			Type:       jobTemplate,
			Tags:       trackNumberParts[1] + "-" + trackNumberParts[2],
			DataCenter: param.Dc[0],
			Env:        "sc",
			Host:       awxHostVarArr,
		}

		var a = gmidwa.CallAwx{
			FuncVar:       funcVar,
			AwxConfigInfo: awxConfigInfo,
		}

		jobID := a.LaunchJobforMonitorApply(funcAwxLaunch)
		deployTime := time.Now().Format("2006-01-02 15:04")
		DB.Table(strings.ToLower(trackNumberParts[1])+"_track_numbers_"+param.Dc[0]).Where("track_number = ?", value.TrackNumber).Update("job_id", jobID)
		DB.Table(strings.ToLower(trackNumberParts[1])+"_track_numbers_"+param.Dc[0]).Where("track_number = ?", value.TrackNumber).Update("deploy_time", deployTime)

		fmt.Println(value.TrackNumber)
	}

	type jsonData struct {
		Code int
		Data string
	}
	data := jsonData{
		Code: 200,
		Data: "success",
	}
	context.JSON(http.StatusOK, data)
}

// 接收前端注册服务信号，注册服务
func PostMonitorApplRegister(context *gin.Context) {

	// var param = []model.ApplyTrackNumber{}
	var param transData
	err := context.BindJSON(&param)
	if err != nil {
		context.JSON(500, gin.H{"err": err})
		log.Printf("ERROR: Register service failed")
		return
	}

	minIndex := make(map[string]int)

	log.Printf("INFO: dc is %v", param.Dc[0])

	if param.Dc[0] == "nm" {
		for _, value := range []string{"nm", "nm-zj"} {
			index := handler.CheckServerVolume(value) // 返回压力最小的集群index
			if index == 0 {
				log.Printf("ERROR: Prometheus server check failed")
				panic("Prometheus server check failed")
			} else {
				minIndex[value] = index
			}
		}

	} else {
		index := handler.CheckServerVolume(param.Dc[0]) // 返回压力最小的集群index
		if index == 0 {
			log.Printf("ERROR: Prometheus server check failed")
			panic("Prometheus server check failed")
		} else {
			minIndex[param.Dc[0]] = index
		}
	}

	// 数据处理
	DB := repository.GetDB()
	var monitorApplRegisterOutCome string
	for _, value := range param.Data {
		// 从数据库中拿数据
		trackNumberParts := strings.Split(value.TrackNumber, "-")
		fmt.Printf("INFO: Track numbers type is %v.", trackNumberParts[1])
		var tableNumber struct {
			TrackNumberTable string
		}
		var monitorApplyData []model.KeywordsApply
		lowerType := strings.ToLower(trackNumberParts[1])
		DB.Table(lowerType+"_track_numbers_"+param.Dc[0]).Where("track_number = ?", value.TrackNumber).Select("track_number_table").Find(&tableNumber)
		DB.Table(lowerType+"_applies_"+param.Dc[0]).Where("track_number = ?", tableNumber.TrackNumberTable).Find(&monitorApplyData)

		// 数据转换为注册服务函数变量类型
		for _, applyDataValue := range monitorApplyData {

			var locDc string
			if param.Dc[0] == "nm" {
				type Dc struct {
					Datacenter string `gorm:"column:datacenter"`
				}
				var dc []Dc
				DB.Table("cmdb_all_servers").Where("ip = ?", applyDataValue.IP).Select("datacenter").Find(&dc)
				if dc[0].Datacenter == "内蒙数据中心-和林" {
					locDc = "nm-zj"
				} else {
					locDc = "nm"
				}
			} else {
				locDc = param.Dc[0]
			}

			serviceData := model.FuncServiceRegister{
				ExporterType: trackNumberParts[1],
				Datacenter:   locDc,
				MinIndex:     strconv.Itoa(minIndex[locDc]),
				TrackNumber:  value.TrackNumber,
				ShortName:    applyDataValue.ShortName,
				Hostname:     applyDataValue.Hostname,
				IP:           applyDataValue.IP,
				AppTeam:      applyDataValue.AppTeam,
				ServiceName:  applyDataValue.ServiceName,
				SystemID:     strconv.Itoa(applyDataValue.SystemID),
			}
			state := handler.ServiceRegisterSingle(minIndex[locDc], serviceData)
			var reOutComeSingle string
			if state {
				reOutComeSingle = applyDataValue.IP + ": " + trackNumberParts[1] + " service register success"
			} else {
				reOutComeSingle = applyDataValue.IP + ": " + trackNumberParts[1] + " service register failed"
			}
			monitorApplRegisterOutCome = monitorApplRegisterOutCome + reOutComeSingle + "\n"
		}
		// 注册服务
	}

	type jsonData struct {
		Code int
		Data string
	}
	data := jsonData{ // 返回前端信息
		Code: 200,
		Data: monitorApplRegisterOutCome,
	}
	context.JSON(http.StatusOK, data)

}
